package com.cskaoyan.wordmemorize.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cskaoyan.wordmemorize.auth.StpKit;
import com.cskaoyan.wordmemorize.common.constant.CommonConstant;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.constant.UserVocBoundEnum;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.common.util.IpUtil;
import com.cskaoyan.wordmemorize.dao.entity.*;
import com.cskaoyan.wordmemorize.dao.mapper.*;
import com.cskaoyan.wordmemorize.dto.admin.AdminLoginDTO;
import com.cskaoyan.wordmemorize.dto.app.AppLoginDTO;
import com.cskaoyan.wordmemorize.request.EmployeeLoginRequest;
import com.cskaoyan.wordmemorize.request.PhoneNumberLoginCommand;
import com.cskaoyan.wordmemorize.service.LoginService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

@Service
@Slf4j
public class LoginServiceImpl extends ServiceImpl<EmployeeMapper, EmployeeDO> implements LoginService {


    @Resource
    UserMapper userMapper;

    @Resource
    UserVocBoundStatisticsMapper userVocBoundStatisticsMapper;

    @Resource
    UserCheckinStatisticsMapper userCheckinStatisticsMapper;

    @Resource
    UserRemindMapper userRemindMapper;

    @Resource
    UserVocBoundLogMapper userVocBoundLogMapper;


    @Override
    public AppLoginDTO phoneNumberLogin(PhoneNumberLoginCommand command, String ipAddr) {

        LambdaQueryWrapper<UserDO> userPhoneWrapper = new LambdaQueryWrapper<>();
        userPhoneWrapper.eq(UserDO::getPhoneNumber, command.getPhoneNumber()).select(UserDO::getId);
        // 判断用户是否存在
        UserDO userDO = userMapper.selectOne(userPhoneWrapper);

        boolean isFirst = false;

        if (userDO == null) {
            isFirst = true;
            // 保存用户信息，相当于注册
            userDO = UserDO.builder().thirdPartyName(command.getDisplayName()).email(command.getEmail()).headImg(command.getPhotoUrl()).phoneNumber(command.getPhoneNumber()).lastLoginIp(ipAddr).nickName(getName()).lastLoginTime(LocalDateTime.now())
                    // 默认等级
                    .levelName(CommonConstant.REGISTER_LEVEL_NAME).levelValue(CommonConstant.REGISTER_LEVEL_VALUE).levelDate(LocalDate.now())
                    // 默认无补签卡
                    .hasSignCard(0)
                    // 默认单词上限
                    // 默认规划的每天单词量
                    .vocCountOfDay(CommonConstant.REGISTER_VOC_OF_DAY).build();
            // 保存用户信息
            userMapper.insert(userDO);

            // vocBoundStatistics`
            UserVocBoundStatisticsDO userVocBoundStatisticsDO = UserVocBoundStatisticsDO.builder().userId(userDO.getId()).total(CommonConstant.REGISTER_VOC_BOUND).available(CommonConstant.REGISTER_VOC_BOUND).pay(0).free(0).occupied(0).exchange(0).build();
            userVocBoundStatisticsMapper.insert(userVocBoundStatisticsDO);

            // userCheckinStatistics
            UserCheckinStatisticsDO userCheckinStatisticsDO = UserCheckinStatisticsDO.builder().userId(userDO.getId()).totalDays(0).curContinuousDays(0).maxContinuousDays(0).totalTime(0L).build();
            userCheckinStatisticsMapper.insert(userCheckinStatisticsDO);

            // remind
            UserRemindDO userRemindDO = UserRemindDO.builder().phoneNumber(userDO.getPhoneNumber()).userId(userDO.getId()).userName(userDO.getNickName()).messageStatus(CommonConstant.DEFAULT_REMIND_MESSAGE_STATUS).remindTime(LocalTime.parse(CommonConstant.DEFAULT_REMIND_TIME)).build();
            userRemindMapper.insert(userRemindDO);


            // vocBoundLog
            UserVocBoundLogDO userVocBoundLogDO = UserVocBoundLogDO.builder().logDate(LocalDate.now()).userId(userDO.getId()).count(CommonConstant.REGISTER_VOC_BOUND).type(UserVocBoundEnum.USER_VOC_BOUND_LOG_REGISTER.getValue()).description(UserVocBoundEnum.USER_VOC_BOUND_LOG_REGISTER.getDescription()).build();
            userVocBoundLogMapper.insert(userVocBoundLogDO);
        }

        // 登录
        StpKit.USER.login(userDO.getId());

        // 更新登录时间
        userDO.setLastLoginTime(LocalDateTime.now());
        userDO.setLastLoginIp(ipAddr);
        userMapper.updateById(userDO);

        AppLoginDTO appLoginDTO = new AppLoginDTO();
        appLoginDTO.setToken(StpUtil.getTokenValue());
//        appLoginDTO.setToken("759abd1b-1d25-4e6f-8af6-1057d497f333");
        appLoginDTO.setIsFirst(isFirst);
        return appLoginDTO;
    }


    protected String getName() {
        Long userCount = userMapper.selectCount(null);
        return CommonConstant.USER_NICK_NAME_PREFIX + (userCount + 1);
    }

    /**
     * 后台登录功能
     *
     * @param request 登录请求
     * @param req     HttpServletRequest 对象
     * @return 登录结果
     */

    @Override
    public AdminLoginDTO adminLogin(EmployeeLoginRequest request, HttpServletRequest req) {
        // 构建查询条件
        LambdaQueryWrapper<EmployeeDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EmployeeDO::getName, request.getUsername()).eq(EmployeeDO::getPassword, SaSecureUtil.md5(request.getPassword()));

        // 查询用户信息
        EmployeeDO employeeDO = getOne(wrapper);

        // 如果用户不存在，抛出异常
        if (employeeDO == null) {
            throw new BusinessException(ResultCodeEnum.LOCAL_LOGIN_FAIL);
        }

        // 存在，则登录
        StpKit.ADMIN.login(employeeDO.getId());

        // 获取 token
        String tokenValue = StpKit.ADMIN.getTokenValue();

        // 获取客户端IP地址
        String ipAddr = IpUtil.getIpAddr(req);

        // 确保 IP 地址不为空
        if (ipAddr == null || ipAddr.trim().isEmpty()) {
            ipAddr = "127.0.0.1"; // 设置默认值
        }

        // 创建新的实体对象进行更新，避免使用原来的对象
        EmployeeDO updateEmployee = new EmployeeDO();
        updateEmployee.setId(employeeDO.getId());
        updateEmployee.setLastLoginIp(ipAddr);
        updateEmployee.setLastLoginTime(LocalDateTime.now());

        // 更新登录信息
        boolean updated = updateById(updateEmployee);

        if (!updated) {
            // 更新失败，记录日志
            log.error("Failed to update login info for employee: {}", employeeDO.getId());
        }

        // 封装返回结果
        AdminLoginDTO adminLoginDTO = new AdminLoginDTO();
        adminLoginDTO.setToken(tokenValue);

        return adminLoginDTO;
    }
}
